/*
 *     This file is part of Mobile GPS Logger.
 *
 *     Mobile GPS Logger is free software: you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation, either version 3 of the
 *     License, or (at your option) any later version.
 *
 *     Mobile GPS Logger is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License v3 for more details.
 *
 *     You should have received a copy of the GNU General Public License v3
 *     along with Mobile GPS Logger. If not, see <http://www.gnu.org/licenses/>.
 */

package cx.ath.skyflyer.gpslog.nmea;

/**
 * Contains functions to calculate and verify checksums in NMEA sentences.
 * @author Ahti Legonkov
 */
public class Checksum {

    /**
     * Calculates a checksum for given string. If the string starts with $, it
     * is ignored. Also everything after the first '*' is ignored.
     * @param s a string to calculate the checksum for.
     * @return checksum.
     */
    public static byte calculate(String s) {
        int end = s.indexOf('*');
        if (end == -1)
            end = s.length();

        byte res = 0;

        int i = 0;
        byte[] bytes = s.getBytes();

        if (bytes[0] == '$')
            i = 1;

        for (; i < end; ++i) {
            byte b = bytes[i];
            res = (byte)(res ^ b);
        }

        return res;
    }

    /**
     * Checks if the checksum in given NMEA sentence is correct or not.
     * @param s an NMEA sentence to check.
     * @return true if checksum is correct, false otherwise.
     * @throws IllegalArgumentException if the string does not contain checksum.
     */
    public static boolean check(String s) throws IllegalArgumentException {
        if (!s.startsWith("$"))
            throw new IllegalArgumentException(s);

        final int end = s.indexOf('*');
        if (end == -1)
            throw new IllegalArgumentException(s);

        final String strChecksum = s.substring(end+1, s.length()).toLowerCase();

        if (strChecksum.length() != 2)
            throw new IllegalArgumentException(s);


        final char [] digits = { '0','1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f' };
        byte checksum = Byte.parseByte(strChecksum, 16);

        return calculate(s) == checksum;
    }
}
